#!/bin/bash
###
 # @Author: lineCode 1145938682@qq.com
 # @Date: 2025-04-17 16:38:40
 # @LastEditors: lineCode 1145938682@qq.com
 # @LastEditTime: 2025-04-22 00:31:30
 # @FilePath: /backend/docker/deploy.sh
### 

MAX_PROCESSES=2  # 设置最大并行进程数

LOG_DIR="./logs"
UPLOADS_DIR="./uploads"
TMP_DIR="./tmp"

GROUP_NAME="shorthand"

# 定义需要更新的服务列表
services=(
    "shorthand-gateway"
    "shorthand-auth"
    "shorthand-modules-system"
    "shorthand-modules-front"
    "shorthand-modules-content"
)
rm -rf "$LOG_DIR"
rm -rf "$UPLOADS_DIR"

mkdir -p "$LOG_DIR"
mkdir -p "$TMP_DIR"
mkdir -p "$UPLOADS_DIR"
chown -R 777 "$UPLOADS_DIR"

TIMESTAMP=$(date +%Y%m%d%H%M%S)

# 创建并行控制 FIFO
fifo="$TMP_DIR/$$.fifo"
mkfifo "$fifo"
exec 3<>"$fifo"
rm -f "$fifo"
# 初始化令牌
for ((i=0; i<MAX_PROCESSES; i++)); do
    echo >&3
done

# 定义带颜色的输出函数
color_echo() {
    local color=$1
    local msg=$2
    case $color in
        red)    echo -e "\033[31m[$(date '+%T')] $msg\033[0m" ;;
        green)  echo -e "\033[32m[$(date '+%T')] $msg\033[0m" ;;
        yellow) echo -e "\033[33m[$(date '+%T')] $msg\033[0m" ;;
        *)      echo "[$(date '+%T')] $msg" ;;
    esac
}

# 安全加载 .env 文件的环境变量
load_env() {
    local env_file="$1"
    while IFS= read -r line || [[ -n "$line" ]]; do
        # 过滤注释和空行
        line="${line%%#*}"          # 去除行末注释
        line="${line//$'\r'/}"      # 去除 Windows 换行符
        line="${line//$'\n'/}"      # 去除换行符
        if [[ -z "$line" ]]; then
            continue
        fi
        
        # 解析键值对
        if [[ "$line" =~ ^([A-Za-z_][A-Za-z0-9_]*)=['"']?(.*)['"']?$ ]]; then
            key="${BASH_REMATCH[1]}"
            value="${BASH_REMATCH[2]}"
            
            # 移除值首尾的匹配引号
            first_char="${value:0:1}"
            last_char="${value: -1}"
            if [[ "$first_char" == "$last_char" && ( "$first_char" == "'" || "$first_char" == '"' ) ]]; then
                value="${value:1:-1}"
            fi
            
            # 导出变量（不污染父Shell环境）
            export "$key"="$value"
        else
            echo "警告: 忽略非法行 - $line"
        fi
    done < "$env_file"
}

# 强制更新镜像
force_update_image() {
    color_echo yellow "⏳ 强制更新镜像..."
    # 停止并删除所有容器及关联资源
    docker-compose -p $GROUP_NAME down --rmi all --volumes --remove-orphans
    # 删除构建缓存（需指定构建时的项目名称）
    docker builder prune --filter label=com.docker.compose.project=$GROUP_NAME -af
    # 强制重新构建（禁用缓存）
    docker-compose -p $GROUP_NAME --env-file .env -f docker-compose.yml build --no-cache --force-rm
}

# 任务执行函数
execute_task() {
    local service=$1
    local log_file="${LOG_DIR}/${service}_${TIMESTAMP}.log"

    # 关键消息输出到终端
    color_echo yellow "➔ 开始处理服务: $service"

    # Docker操作日志写入文件
    {
        echo "====== 详细操作日志 ======"
        echo "服务名称: $service"
        echo "镜像版本: ${TAG}"
        echo "开始时间: $(date)"
        
        # 执行更新操作，启动服务（强制重建）
        if docker-compose -p $GROUP_NAME --env-file .env -f docker-compose.yml up -d --force-recreate --no-deps "$service"; then
            echo "Docker操作成功"
        else
            echo "Docker操作失败"
            return 1
        fi
        
        # 清理旧镜像
        docker images --format "{{.Tag}}" --filter "reference=${service}*" \
        | sort -k1,1r -k2,2Vr \
        | tail -n +4 \
        | xargs -I {} docker rmi "${service}:{}"
        
        echo "结束时间: $(date)"
    } >> "$log_file" 2>&1

    # 返回处理结果
    # shellcheck disable=SC2320
    if [ $? -eq 0 ]; then
        color_echo green "✓ 成功完成: $service, 版本号: $TAG"
        return 0
    else
        color_echo red "✗ 处理失败: $service, 版本号: $TAG"
        return 1
    fi
}


color_echo green "====== 开始部署 ======"

# 加载 .env 文件
load_env ".env"
force_update_image

# 滚动更新服务（零停机部署）（兼容旧版 Bash）
for service in "${services[@]}"; do
    # 获取令牌
    read -u3
    {   
        # 启动后台任务
        execute_task "$service"
        # 归还令牌
        echo >&3
    } &
done

# 等待剩余的后台进程完成
wait
exec 3>&-

# 清理临时目录
rm -rf "$TMP_DIR"  

# 最终状态汇总
color_echo green "====== 部署结果汇总 ======"
for service in "${services[@]}"; do
    if grep -q "Docker操作成功" "${LOG_DIR}/${service}"_*.log; then
        color_echo green "[${service}] 部署成功，版本号: ${TAG}, 日志: ${LOG_DIR}/${service}_*.log"
    else
        color_echo red "[${service}] 部署失败, 日志: ${LOG_DIR}/${service}_*.log"
    fi
done

color_echo green "====== 部署完成 ======"